#pragma once
#include <gfx/vk/vk_common.h>
#include <array>
#include <common_header.h>

namespace primal
{
	namespace vkx
	{
		constexpr uint32_t vkx_version{ VK_MAKE_VERSION(0, 0, 1) };
		constexpr auto vkx_name{ "vkx" };
		constexpr auto shader_entry_pointer{ "main" };

#ifdef _WINDOWS
#define vk_platform_surface_name "VK_KHR_win32_surface"
#else
#define vk_platform_surface_name "VK_KHR_xcb_surface"
#endif // _WINDOWS

#ifdef NDEBUG
		constexpr std::array<const char*, 2> vkx_extensions
		{
			VK_KHR_SURFACE_EXTENSION_NAME,
			vk_platform_surface_name,
	    };

		constexpr std::array<const char*, 0> vkx_layers{};

		constexpr std::array<const char*, 1> vkx_device_extensions
		{
			VK_KHR_SWAPCHAIN_EXTENSION_NAME
		};

		constexpr std::array<const char*, 0> vkx_device_layers{};
#else
		constexpr std::array<const char*, 3> vkx_extensions
		{
			VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
			VK_KHR_SURFACE_EXTENSION_NAME,
			vk_platform_surface_name,
		};

		constexpr std::array<const char*, 1> vkx_layers
		{
			"VK_LAYER_KHRONOS_validation" 
		};

		constexpr std::array<const char*, 1> vkx_device_extensions
		{
			VK_KHR_SWAPCHAIN_EXTENSION_NAME 
		};

		constexpr std::array<const char*, 0> vkx_device_layers{};
#endif

		constexpr struct
		{
			VkCommandBufferBeginInfo cmd_begin_info
			{
				VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
				nullptr,
				VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
				nullptr
			};

			VkFenceCreateInfo fence_create_info
			{
				VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,        //VkStructureType           sType;
				nullptr,                                    //const void*               pNext;
				VK_FENCE_CREATE_SIGNALED_BIT                //VkFenceCreateFlags        flags;
			};

			VkSemaphoreCreateInfo semaphore_create_info
			{
				VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,    //VkStructureType           sType;
				nullptr,                                    //const void*               pNext;
				0                                           //VkSemaphoreCreateFlags    flags;
			};

			VkPipelineVertexInputStateCreateInfo vertex_input_null
			{
				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,//VkStructureType                             sType;
				nullptr,//const void* pNext;
				0,//VkPipelineVertexInputStateCreateFlags       flags;
				0u,//uint32_t                                    vertexBindingDescriptionCount;
				nullptr,//const VkVertexInputBindingDescription* pVertexBindingDescriptions;
				0u,//uint32_t                                    vertexAttributeDescriptionCount;
				nullptr//const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
			};

			VkPipelineInputAssemblyStateCreateInfo input_assembly
			{
				VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,//VkStructureType                            sType;
				nullptr,//const void* pNext;
				0,//VkPipelineInputAssemblyStateCreateFlags    flags;
				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,//VkPrimitiveTopology                        topology;
				VK_FALSE//VkBool32                                   primitiveRestartEnable;
			};

			VkPipelineViewportStateCreateInfo viewport_null
			{
				VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,//VkStructureType                       sType;
				nullptr,//const void* pNext;
				0,//VkPipelineViewportStateCreateFlags    flags;
				1,//uint32_t                              viewportCount;
				nullptr,//const VkViewport* pViewports;
				1,//uint32_t                              scissorCount;
				nullptr//const VkRect2D* pScissors;
			};

			VkFormat color_format{ VK_FORMAT_B8G8R8A8_UNORM };
			VkFormat depth_format{ VK_FORMAT_D24_UNORM_S8_UINT };
		}def{};

		constexpr struct
		{
			std::array<VkDynamicState, 2> viewports{ VK_DYNAMIC_STATE_VIEWPORT ,VK_DYNAMIC_STATE_SCISSOR };
		}dynamic_states{};

		constexpr struct
		{
			VkPipelineDynamicStateCreateInfo vieweport
			{
				VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,//sType;
				nullptr,//pNext;
				0,//flags;
				dynamic_states.viewports.size(),//dynamicStateCount;
				dynamic_states.viewports.data()//pDynamicStates;
			};
		}dynamic_state_create_infos{};

		constexpr struct
		{
			std::array<VkPipelineColorBlendAttachmentState, 1> base
			{
				{
					VK_FALSE,																								  //VkBool32                 blendEnable;
					VK_BLEND_FACTOR_ZERO,																					  //VkBlendFactor            srcColorBlendFactor;
					VK_BLEND_FACTOR_ZERO,																					  //VkBlendFactor            dstColorBlendFactor;
					VK_BLEND_OP_ADD,																						  //VkBlendOp                colorBlendOp;
					VK_BLEND_FACTOR_ZERO,																					  //VkBlendFactor            srcAlphaBlendFactor;
					VK_BLEND_FACTOR_ZERO,																					  //VkBlendFactor            dstAlphaBlendFactor;
					VK_BLEND_OP_ADD,																						  //VkBlendOp                alphaBlendOp;
					VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT //VkColorComponentFlags    colorWriteMask;
				}
			};
		}color_blend_attachment_state_list{};

		constexpr struct
		{
			VkPipelineColorBlendStateCreateInfo ui
			{
				VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,			//VkStructureType                               sType;			  
				nullptr,															//const void*                                   pNext;			  
				0,																	//VkPipelineColorBlendStateCreateFlags          flags;			  
				VK_FALSE,															//VkBool32                                      logicOpEnable;	  
				VK_LOGIC_OP_COPY,													//VkLogicOp                                     logicOp;		  
				color_blend_attachment_state_list.base.size(),						//uint32_t                                      attachmentCount;  
				color_blend_attachment_state_list.base.data(),						//const VkPipelineColorBlendAttachmentState*    pAttachments;	  
				{0.f,0.f,0.f,0.f}													//float                                         blendConstants[4];
			};
		}color_blend_state_create_infos{};

		constexpr struct
		{
			VkPipelineMultisampleStateCreateInfo multisample_state
			{
				VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,			//VkStructureType                          sType;
				nullptr,															//const void*                              pNext;
				0,																	//VkPipelineMultisampleStateCreateFlags    flags;
				VK_SAMPLE_COUNT_1_BIT,												//VkSampleCountFlagBits                    rasterizationSamples;
				VK_FALSE,															//VkBool32                                 sampleShadingEnable;
				0.0f,																//float                                    minSampleShading;
				nullptr,															//const VkSampleMask*                      pSampleMask;
				VK_FALSE,															//VkBool32                                 alphaToCoverageEnable;
				VK_FALSE															//VkBool32                                 alphaToOneEnable;
			};
		}multisample_state_create_infos{};

		constexpr struct
		{
			VkPipelineRasterizationStateCreateInfo rasterization_state
			{
				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,			 //sType
				nullptr,															 //pNext
				0,																	 //flags
				VK_FALSE,															 //depthClampEnable
				VK_FALSE,															 //rasterizerDiscardEnable
				VK_POLYGON_MODE_FILL,												 //polygonMode
				VK_CULL_MODE_FRONT_AND_BACK,										 //cullMode
				VK_FRONT_FACE_CLOCKWISE,											 //frontFace
				VK_FALSE,															 //depthBiasEnable
				0.0f,																 //depthBiasConstantFactor
				0.0f,																 //depthBiasClamp
				0.0f,																 //depthBiasSlopeFactor
				1.0f																 //lineWidth
			};
		}rasterization_state_create_infos{};

		constexpr struct
		{
			std::array<VkAttachmentDescription, 1> color_attachment
			{
				{
					0,											   //VkAttachmentDescriptionFlags    flags;
					def.color_format,							   //VkFormat                        format;
					VK_SAMPLE_COUNT_1_BIT,						   //VkSampleCountFlagBits           samples;
					VK_ATTACHMENT_LOAD_OP_CLEAR,				   //VkAttachmentLoadOp              loadOp;
					VK_ATTACHMENT_STORE_OP_STORE,				   //VkAttachmentStoreOp             storeOp;
					VK_ATTACHMENT_LOAD_OP_DONT_CARE,			   //VkAttachmentLoadOp              stencilLoadOp;
					VK_ATTACHMENT_STORE_OP_DONT_CARE,			   //VkAttachmentStoreOp             stencilStoreOp;
					VK_IMAGE_LAYOUT_UNDEFINED,					   //VkImageLayout                   initialLayout;
					VK_IMAGE_LAYOUT_PRESENT_SRC_KHR				   //VkImageLayout                   finalLayout;
				}
			};
		}attachment_description_list{};

		constexpr struct
		{
			std::array<VkAttachmentReference, 1> color_reference
			{
				{
					0u,
					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
				}
			};
		}attachment_reference_list{};

		constexpr struct
		{
			std::array<VkSubpassDescription, 1> ui
			{
				{
					0,														//flags;
					VK_PIPELINE_BIND_POINT_GRAPHICS,						//pipelineBindPoint;
					0u,														//inputAttachmentCount;
					nullptr,												//pInputAttachments;
					attachment_reference_list.color_reference.size(),		//colorAttachmentCount;
					attachment_reference_list.color_reference.data(),		//pColorAttachments;
					nullptr,												//pResolveAttachments;
					nullptr,												//pDepthStencilAttachment;
					0u,														//preserveAttachmentCount;
					nullptr													//pPreserveAttachments;
				}
			};
		}subpass_description_list{};

		constexpr struct
		{
			std::array<VkSubpassDependency, 1> ui
			{
				{
					VK_SUBPASS_EXTERNAL,									//uint32_t                srcSubpass;
					0u,														//uint32_t                dstSubpass;
					VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			//VkPipelineStageFlags    srcStageMask;
					VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			//VkPipelineStageFlags    dstStageMask;
					0,														//VkAccessFlags           srcAccessMask;
					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					//VkAccessFlags           dstAccessMask;
					0														//VkDependencyFlags       dependencyFlags;
				}
			};
		}subpass_dependency_list{};

		constexpr struct
		{
			VkRenderPassCreateInfo ui
			{
				VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,					 //VkStructureType                   sType;
				nullptr,													 //const void*						 pNext;
				0,															 //VkRenderPassCreateFlags           flags;
				attachment_description_list.color_attachment.size(),		 //uint32_t                          attachmentCount;
				attachment_description_list.color_attachment.data(),		 //const VkAttachmentDescription*	 pAttachments;
				subpass_description_list.ui.size(),							 //uint32_t                          subpassCount;
				subpass_description_list.ui.data(),							 //const VkSubpassDescription*		 pSubpasses;
				subpass_dependency_list.ui.size(),							 //uint32_t                          dependencyCount;
				subpass_dependency_list.ui.data()							 //const VkSubpassDependency*        pDependencies;
			};
		}render_pass_create_info_list{};


		constexpr struct
		{
			std::array<VkDescriptorPoolSize, 4> all_sizes
			{
				VkDescriptorPoolSize{
					VK_DESCRIPTOR_TYPE_SAMPLER,
					1024u
				},
				VkDescriptorPoolSize{
					VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
					1024u
                },
				VkDescriptorPoolSize{
					VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
					1024u
				},
				VkDescriptorPoolSize{
					VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
					1024u
				}
			};
		}descriptor_pool_size_list{};

		constexpr struct
		{
			VkDescriptorPoolCreateInfo all_pool
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
				nullptr,
				0,
				1024u,
				descriptor_pool_size_list.all_sizes.size(),
				descriptor_pool_size_list.all_sizes.data()
			};
		}descriptor_pool_create_infos{};

		struct instance_create_info : VkInstanceCreateInfo
		{
			VkInstanceCreateInfo* init()
			{
				this->_app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
				this->_app_info.apiVersion = VK_API_VERSION_1_3;
				this->_app_info.applicationVersion = vkx_version;
				this->_app_info.engineVersion = vkx_version;
				this->_app_info.pEngineName = vkx_name;
				this->_app_info.pApplicationName = vkx_name;
				this->_app_info.pNext = nullptr;

				sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				pApplicationInfo = &_app_info;
				enabledLayerCount = static_cast<uint32_t>(vkx_layers.size());
				ppEnabledLayerNames = vkx_layers.data();
				enabledExtensionCount = static_cast<uint32_t>(vkx_extensions.size());
				ppEnabledExtensionNames = vkx_extensions.data();

				return this;
			}

		private:
			VkApplicationInfo _app_info;
		};

		template <u32 family_count>
		struct device_create_info : VkDeviceCreateInfo
		{
			void init_queue(u32 fam_index, u32 fam_id, float* priorites, size_t count)
			{
				VkDeviceQueueCreateInfo& info{ queue_create_infos[fam_index] };
				info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
				info.pNext = nullptr;
				info.flags = 0;
				info.queueFamilyIndex = fam_id;
				info.queueCount = count;
				info.pQueuePriorities = priorites;
			}

			VkDeviceCreateInfo* init()
			{
				features = {};
				sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				queueCreateInfoCount = family_count;
				pQueueCreateInfos = queue_create_infos;
				enabledLayerCount = static_cast<u32>(vkx_device_layers.size());
				ppEnabledLayerNames = vkx_device_layers.data();
				enabledExtensionCount = static_cast<u32>(vkx_device_extensions.size());
				ppEnabledExtensionNames = vkx_device_extensions.data();
				pEnabledFeatures = &features;
				return this;
			}

		private:
			VkDeviceQueueCreateInfo queue_create_infos[family_count];
			VkPhysicalDeviceFeatures features;
		};

		struct debug_create_info
		{
			VkDebugReportCallbackCreateInfoEXT* as_report(PFN_vkDebugReportCallbackEXT callback)
			{
				report_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
				report_info.pNext = nullptr;
				report_info.flags = 0;
				report_info.pfnCallback = callback;
				report_info.pUserData = nullptr;
				return &report_info;
			}

			VkDebugUtilsMessengerCreateInfoEXT* as_utils(PFN_vkDebugUtilsMessengerCallbackEXT callback)
			{
				utils_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
				utils_info.pNext = nullptr;
				utils_info.flags = 0;
				utils_info.messageSeverity = 0x1111;
				utils_info.messageType = 0b1111;
				utils_info.pfnUserCallback = callback;
				utils_info.pUserData = nullptr;
				return &utils_info;
			}

		private:
			union
			{
				VkDebugReportCallbackCreateInfoEXT report_info;
				VkDebugUtilsMessengerCreateInfoEXT utils_info;
			};
		};

		struct swapchain_create_info : VkSwapchainCreateInfoKHR
		{
			VkSwapchainCreateInfoKHR* init(VkSurfaceKHR sur, u32 count, u32 width, u32 height)
			{
				imageExtent.width = width;                                              //VkExtent2D                       imageExtent;
				imageExtent.height = height;                                            //VkExtent2D                       imageExtent;
				sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;                    //VkStructureType                  sType;
				pNext = nullptr;                                                        //const void*                      pNext;
				flags = 0;                                                              //VkSwapchainCreateFlagsKHR        flags;
				surface = sur;                                                          //VkSurfaceKHR                     surface;
				minImageCount = count;                                                  //uint32_t                         minImageCount;
				imageFormat = def.color_format;                                         //VkFormat                         imageFormat;
				imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;                    //VkColorSpaceKHR                  imageColorSpace;
				imageArrayLayers = 1u;                                                  //uint32_t                         imageArrayLayers;
				imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;                       //VkImageUsageFlags                imageUsage;
				imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;                           //VkSharingMode                    imageSharingMode;
				queueFamilyIndexCount = 0u;                                             //uint32_t                         queueFamilyIndexCount;
				pQueueFamilyIndices = nullptr;                                          //const uint32_t*                  pQueueFamilyIndices;
				preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;                   //VkSurfaceTransformFlagBitsKHR    preTransform;
				compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;                     //VkCompositeAlphaFlagBitsKHR      compositeAlpha;
				presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;                            //VkPresentModeKHR                 presentMode;
				clipped = VK_TRUE;                                                      //VkBool32                         clipped;
				oldSwapchain = nullptr;                                                 //VkSwapchainKHR                   oldSwapchain;
				return this;
			}
		};

		struct shader_create_info : VkShaderModuleCreateInfo
		{
			VkShaderModuleCreateInfo* init(u32 size, void* data)
			{
				sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				codeSize = size;
				pCode = static_cast<u32*>(data);
				return this;
			}
		};

		struct image_view_create_info : VkImageViewCreateInfo
		{
			VkImageViewCreateInfo* init(VkImage img)
			{
				sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				image = img;
				viewType = VK_IMAGE_VIEW_TYPE_2D;
				format = def.color_format;

				components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
				components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
				components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
				components.a = VK_COMPONENT_SWIZZLE_IDENTITY;

				subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
				subresourceRange.baseMipLevel = 0;
				subresourceRange.levelCount = 1;
				subresourceRange.baseArrayLayer = 0;
				subresourceRange.layerCount = 1;

				return this;
			}
		};

		struct shader_states
		{
			void add_vs(VkShaderModule handle)
			{
				auto& inf{ _infos[_size] };
				inf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
				inf.stage = VK_SHADER_STAGE_VERTEX_BIT;
				inf.module = handle;
				inf.pName = shader_entry_pointer;
				++_size;
			}

			void add_ps(VkShaderModule handle)
			{
				auto& inf{ _infos[_size] };
				inf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
				inf.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
				inf.module = handle;
				inf.pName = shader_entry_pointer;
				++_size;
			}

			void reset()
			{
				_size = 0u;
			}

			VkPipelineShaderStageCreateInfo* get()
			{
				return _infos;
			}

			u32 size()
			{
				return _size;
			}
		private:
			VkPipelineShaderStageCreateInfo _infos[6];
			u32 _size;
		};

		struct rasterization_state_create_info : VkPipelineRasterizationStateCreateInfo
		{

		};

		template<u32 ATTACH_COUNT, u32 SUB_COUNT, u32 DEP_COUNT>
		struct render_pass_create_info : VkRenderPassCreateInfo
		{
			VkRenderPassCreateInfo* init()
			{
				sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
				attachmentCount = ATTACH_COUNT;
				pAttachments = attachments;
				subpassCount = SUB_COUNT;
				pSubpasses = subpasses;
				dependencyCount = DEP_COUNT;
				pDependencies = sub_dependencys;

				return this;
			}

			void init_attach(u32 index)
			{
				VkAttachmentDescription& colorAttachment{ attachments[index] };
				colorAttachment.format = def.color_format;
				colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
				colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
				colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
				colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
				colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
				colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
				colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
			}

			void init_sub_pass(u32 index, VkAttachmentReference* refs, u32 count)
			{
				VkSubpassDescription& subpass{ subpasses[index] };
				subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
				subpass.pColorAttachments = refs;
				subpass.colorAttachmentCount = count;
			}

			void init_sub_dep(u32 index)
			{
				VkSubpassDependency& dependency{ sub_dependencys[index] };
				dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
				dependency.dstSubpass = 0;
				dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
				dependency.srcAccessMask = 0;
				dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
				dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
			}

			VkAttachmentDescription attachments[ATTACH_COUNT];
			VkSubpassDescription subpasses[SUB_COUNT];
			VkSubpassDependency sub_dependencys[DEP_COUNT];
		};

		using base_render_pass_create_info = render_pass_create_info<1, 1, 1>;

		template<u32 RANGE_COUNT>
		struct pipeline_layout_create_info : VkPipelineLayoutCreateInfo
		{
		private:
			VkPushConstantRange range[RANGE_COUNT];
		};

		template<>
		struct pipeline_layout_create_info<0> : VkPipelineLayoutCreateInfo
		{
			VkPipelineLayoutCreateInfo* init()
			{
				sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				setLayoutCount = 0;
				pSetLayouts = nullptr;
				pushConstantRangeCount = 0;
				pPushConstantRanges = nullptr;
				return this;
			}
		};

		template<u32 COUNT>
		struct dynamic_state_create_info : VkPipelineDynamicStateCreateInfo
		{
			VkPipelineDynamicStateCreateInfo* init()
			{
				sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				dynamicStateCount = COUNT;
				pDynamicStates = states;

				return this;
			}
			VkDynamicState& operator[](u32 index)
			{
				return states[index];
			}
		private:
			VkDynamicState states[COUNT];
		};

		struct command_pool_create_info : VkCommandPoolCreateInfo
		{
			VkCommandPoolCreateInfo* init(u32 family_id, VkFlags flag)//VkCommandPoolCreateFlagBits	
			{
				sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
				pNext = nullptr;
				flags = flag;
				queueFamilyIndex = family_id;
				return this;
			}
		};

		struct command_buffer_info : VkCommandBufferAllocateInfo
		{
			VkCommandBufferAllocateInfo* init(VkCommandPool pool, u32 count)
			{
				sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
				pNext = nullptr;
				commandPool = pool;
				level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
				commandBufferCount = count;
				return this;
			}
		};

		struct frame_buffer_create_info : VkFramebufferCreateInfo
		{
			VkFramebufferCreateInfo* init(VkRenderPass rp, u32 count, VkImageView* attachs, u32 w, u32 h)
			{
				sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
				pNext = nullptr;
				flags = 0;
				renderPass = rp;
				attachmentCount = count;
				pAttachments = attachs;
				width = w;
				height = h;
				layers = 1u;

				return this;
			}
		};

		template<u32 SWAP_COUNT>
		struct present_info
		{

		};

		template<>
		struct present_info<1u> : VkPresentInfoKHR
		{
			present_info() :validation_semaphore{}, swapchain{}, swapindex{}
			{
				sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
				pNext = nullptr;
				swapchainCount = 1u;
				pSwapchains = &swapchain;
				pImageIndices = &swapindex;
			}

			VkPresentInfoKHR* reset(VkSemaphore* waitobject, u32 count)
			{
				waitSemaphoreCount = count;
				pWaitSemaphores = waitobject;
				return this;
			}

			VkPresentInfoKHR* reset(VkSemaphore* waitobject)
			{
				waitSemaphoreCount = 1u;
				pWaitSemaphores = waitobject;
				return this;
			}
			VkSemaphore validation_semaphore;
			VkSwapchainKHR swapchain;
			u32 swapindex;
		};

		struct descriptor_set_allocate_info : VkDescriptorSetAllocateInfo
		{
			VkDescriptorSetAllocateInfo* init(VkDescriptorPool pool)
			{
				sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
				pNext = nullptr;
				descriptorPool = pool;
				descriptorSetCount;
				pSetLayouts;
			}
		};

		struct descriptor_pool_create_info : VkDescriptorPoolCreateInfo
		{

		};
		//VkDescriptorPoolSize

	} // namespace vkx

} // namespace primal
